var validator = {
	/**
	 * 可选项，可以根据需要覆盖
	 */
	'options' : {
		/**
		 * 若在元素上使用filters或pattern，则当匹配出错
		 * 时即会调用这里的错误信息。
		 */
		 'errors' : {
		 	//'元素的name属性' : '提示信息'
		 },
		 /**
		  * 内建模板
		  */
		'tpls' : {
			'required' : '此项不能为空！',
			'email' : '错误的邮箱地址！',
			'mobile' : '错误的手机号码！',
			'telephone' : '错误的电话号码！',
			'phone' : '请填写正确的手机号码或电话号码！',
			'name' : '此项只能由(a-z,0-9,_)组成！',
			'name_zh' : '此项只能由(中文,a-z,0-9,_)组成！',
			'password' : '此项只能由(a-z,A-Z,0-9,_)组成！',
			'idcard' : '错误的身份证号码！',
			'pattern' : '匹配失败！',
			'maxLength' : '此项的最大长度为{num}个字符！',
			'minLength' : '此项的最小长度为{num}个字符！',
			'max' : '此项的最大值为{num}！',
			'min' : '此项的最小值为{num}！',
			'not_equal' : '两次输入不一致！',
			'date' : '错误的时间格式！',
			'legal' : ''//如果需要在匹配成功后显示信息可以覆盖此项
		},
		/**
		 * 错误提示信息元素ID的前缀
		 */
		'PREFIX_TIP' : 'tip_',
		/**
		 * 匹配正确时tip的class name
		 */
		'TIP_CLASS_LEGAL' : 'legal',
		/**
		 * 匹配出错时tip的class name
		 */
		'TIP_CLASS_INVALID' : 'invalid'
	},
	/**
	 * 内建的pattern
	 */
	'patterns' : {
		'comm_zh' : '\\u4E00-\\uFA29\\uE7C7-\\uE7F3',
		'comm_09' : '0-9',
		'comm_az' : 'a-z',
		'comm_AZ' : 'A-Z',
		'email' : '^([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\\_|\\.]?)*[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}$',
		'mobile' : '^(13[0-9]|15[012356789]|18[0236789]|14[57])[0-9]{8}$',//手机号码
		'telephone' : '^(\\d{3,4}\\-)?\\d{7,8}$',//电话号码
		'idcard' : '^(\\d{15}|\\d{18})$',//身份证号码
		'name' : '^[a-z0-9_]+$',
		'name_zh' : '^[\\u4E00-\\uFA29\\uE7C7-\\uE7F3a-z0-9]+$',
		'password' : '^[a-zA-Z0-9_]+$'
	},
	/**
	 * 根据提供的参数生成RegExt对象供simpleTest使用
	 * @param types - 可以是zh,09,az,AZ
	 * @param flags - RegExp对应的第二个参数
	 * @return - 返回RegExp对象
	 */
	'getRegExp' : function(types, flags) {
		var pattern = '^[';
		if(typeof(types) == 'string') {
			pattern += validator.patterns['comm_' + types];
		} else {
			for(var i in types) {
				pattern += validator.patterns['comm_' + types[i]] || '';
			}
		}
		pattern += ']+$';
		return new RegExp(pattern, flags);
	},
	/**
	 * 提供一些简单的匹配功能
	 * @param str - 被测试的字符串
	 * @param types - 对应getRegExp的第一个参数
	 * @param flags - 对应getRegExp的第二个参数
	 * @return - 匹配成功返回true，否则返回false
	 */
	'simpleTest' : function(str, types, flags) {
		var re = validator.getRegExp(types, flags);
		return re.test(str);
	},
	/**
	 * 测试是否为邮箱地址
	 */
	'is_email' : function(str) {
		return new RegExp(validator.patterns.email).test(str);
	},
	/**
	 * 测试是否是手机号码
	 */
	'is_mobile' : function(str) {
		return new RegExp(validator.patterns.mobile).test(str);
	},
	/**
	 * 测试是否是电话号码
	 */
	'is_telephone' : function(str) {
		return new RegExp(validator.patterns.telephone).test(str);
	},
	/**
	 * 测试是否是电话号码或手机号码
	 */
	'is_phone' : function(str) {
		return new RegExp(validator.patterns.mobile).test(str) || new RegExp(validator.patterns.telephone).test(str);
	},
	/**
	 * 测试是否是英文名
	 */
	'is_name' : function(str) {
		return new RegExp(validator.patterns.name).test(str);
	},
	/**
	 * 测试是否是中文名
	 */
	'is_name_zh' : function(str) {
		return new RegExp(validator.patterns.name_zh).test(str);
	},
	/**
	 * 测试是否是密码
	 */
	'is_password' : function(str) {
		return new RegExp(validator.patterns.password).test(str);
	},
	/**
	 * 测试是否是身份证号码
	 */
	'is_idcard' : function(str) {
		return new RegExp(validator.patterns.idcard).test(str);
	},
	/**
	 * 检测是否是时间，能否解析成功取决于Date.parse的执行结果
	 */
	'is_date' : function(str) {
		return !isNaN(Date.parse(str));
	},
	/**
	 * 通用的匹配功能
	 */
	'test' : function(str, pattern, flags) {
		return new RegExp(pattern, flags).test(str);
	},
	/**
	 * 初始化表单，为表单元素添加事件
	 * @param formid - 需要表单验证的表单的ID
	 * @param bAddListener - 是否需要拦截表单提交事件
	 * @param checkAll - 对应checkForm第一个参数
	 */
	'setForm' : function(formid, bAddListener, checkAll) {
		function _initElem(elem) {
			var type = elem.type;
			if('text' == type || 'textarea' == type || 'password' == type) {
				elem.onkeyup = function() {
					validator.validate(elem, type);
				}
			}
		}
		
		validator.form = document.getElementById(formid);
		var elems = validator.form.elements;
		for(var i = 0; i < elems.length; i++) {
			_initElem(elems[i]);
		}
		if(bAddListener) {
			validator.form.onsubmit = function() {
				return validator.checkForm(checkAll);
			}
		}
	},
	/**
	 * 检测text,textarea元素是否符合设定规则
	 */
	'validate' : function(elem) {
		var name = elem.name;
		if(name != '') {
			var NUM = '{num}';
			var text = elem.value;
			var required = elem.getAttribute('required');
			var max = elem.getAttribute('max');
			var min = elem.getAttribute('min');
			var maxLength = elem.getAttribute('maxLength');
			var minLength = elem.getAttribute('minLength');
			var filters = elem.getAttribute('filters');
			var pattern = elem.getAttribute('pattern');
			var subType = elem.getAttribute('subType');
			var equalTo = elem.getAttribute('equalTo');
			var flags = elem.getAttribute('flags') || '';
			if(text == '') {
				if(!required) {
					return validator.showTip(name, '', true);
				}
				
				return validator.showTip(name, validator.options.tpls.required, false);
			}

			if(filters && !validator.simpleTest(text, filters.split(','), flags)) {
				return validator.showTip(name, validator.options.errors[name] || validator.options.tpls.pattern, false);
			}
			
			if(pattern && !validator.test(text, pattern, flags)) {
				return validator.showTip(name, validator.options.errors[name] || validator.options.tpls.pattern, false);
			}
			
			if(subType) {
				var funcName = 'is_' + subType.toLowerCase();
				var func = validator[funcName];
				if(func && !func(text)) {
					return validator.showTip(name, validator.options.tpls[subType], false);
				}
			}
			
			var len = text.length;
			if(maxLength && len > maxLength) {
				return validator.showTip(name, validator.options.tpls.maxLength.replace(NUM, maxLength), false);
			}
			
			if(minLength && len < minLength) {
				return validator.showTip(name, validator.options.tpls.minLength.replace(NUM, minLength), false);
			}
			
			var val = parseInt(text);
			if(max && val > max) {
				return validator.showTip(name, validator.options.tpls.max.replace(NUM, max), false);
			}
			
			if(min && val < min) {
				return validator.showTip(name, validator.options.tpls.min.replace(NUM, min), false);
			}
			
			if(equalTo) {
				var elem2 = document.getElementsByName(equalTo)[0];
				if(elem2 && elem2.value != text) {
					return validator.showTip(name, validator.options.tpls.not_equal, false);
				}
			}
			
			return validator.showTip(name, validator.options.tpls.legal, true);
		}
	},
	/**
	 * 检测setForm设定的表单
	 * @param checkAll - 当checkAll为true时，将检查全部元素而不管是否之前已经出错
	 * @return - 表单没有错误返回true,否则返回false
	 */
	'checkForm' : function(checkAll) {
		var b = true;
		for(var i = 0; i < validator.form.elements.length; i++) {
			var elem = validator.form.elements[i];
			var type = elem.type;
			var name = elem.name;
			if(name != '' && ('text' == type || 'textarea' == type || 'password' == type)) {
				if(!validator.validate(elem, type)) {
					b = false;
					if(!checkAll) break;
				}
			}
		}
		
		return b;
	},
	/**
	 * 显示tip
	 */
	'showTip' : function(name, msg, b) {
		var tip = document.getElementById(validator.options.PREFIX_TIP + name);
		if(tip) {
			tip.innerHTML = msg;
			tip.className = b ? validator.options.TIP_CLASS_LEGAL : validator.options.TIP_CLASS_INVALID;
		}
		
		return b;
	}
};